<?php
use app\common\facade\Log;
use think\facade\Config;
use think\facade\Db;

// 应用公共文件
function getOrderTradeNo($user_id)
{
    return date('YmdHis') . rand(10000,99999) . $user_id;
}

function httpHelper($url, $data, $header = null)
{
    $user_agent = 'Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.1;+SV1)';
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    if ($header) {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    }
    // 返回结果
    $r = curl_exec($ch);

    if (is_array($data)){
        $data = json_encode($data);
    }
    Log::info('httpHelper:url=>' . $url . ' Param=>' . $data . ' res=>' . $r);
    // 检查是否有错误发生
    if ($r === false) {
        // 获取并打印 cURL 错误信息
        $error = curl_error($ch);
        Log::info('httpHelper-error:'.$error);
    }
    curl_close($ch);
    if (isset($error) && $error){
        $r = json_decode($r);
        $r['error_msg'] =  $error;
        $r = json_encode($r);
    }
    return $r;
}

/**
 * curlGet请求
 * @param $url
 * @return bool|string
 * @Function:httpGet
 * @Date: 2022/11/24
 * @Time: 20:57
 */
function httpGet($url)
{
	Log::info('httpHelper:url=>' . $url);
	$curl = curl_init();
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($curl, CURLOPT_TIMEOUT, 500);
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
	curl_setopt($curl, CURLOPT_URL, $url);
	$res = curl_exec($curl);
	curl_close($curl);
	return $res;
}

//检测当前为生产环境
function checkSystemProductionEnv()
{
	return env('VERSIONS', 'production') == 'production';
}

function format_transform($time){
	$duration  = explode(":",$time);
	if (count($duration)!=3){
		return 0;
	}
	$duration_in_seconds = $duration[0]*3600 + $duration[1]*60+ round($duration[2]);
	return $duration_in_seconds;
}

/**
 * 秒转换时分秒
 * @param $seconds
 * @param $type
 * @return false|float|int|string
 */
function initTime($seconds, $type = '')
{
	switch ($type) {
		case 'h':
			$H = floor($seconds / 3600);
			$time = $H;
			break;
		case 'i':
			if ($seconds < 60) {
				return 0;
			}
			$i = intval($seconds / 60);
			$time = $i;
			break;
		default:
			$H = floor($seconds / 3600);
			$i = ($seconds / 60) % 60;
			$s = $seconds % 60;
			$time = sprintf("%02d:%02d:%02d", $H, $i, $s);
			break;
	}
	return $time;
}

function getOnlineTime(int $start_time = 0, int $end_time = 0)
{
	if (empty($start_time)) $start_time = time();
	if (empty($end_time)) $end_time = time();
	$diffTime = $end_time - $start_time;
	$times = gmstrftime('%H:%M:%S', $diffTime);
	return empty($times) ? '00:00:00' : $times;
}


/**
 * 数组排序并去重
 * @param array $array
 * @return array
 */
function arraySortUnique(array $array = [])
{
	$result = [];
	foreach ($array as $key => $item) {
		if (isset($item['uuid'])){
			$result[$item['uuid']] = $item;
		}
	}
	return $result;
}

/**
 * 二维数组去重
 * @param array $array
 * @param $key
 * @return array
 * @Function:arrayUnique
 * @Date: 2022/11/23
 * @Time: 19:28
 */
function arrayUnique(array $array = [], $key)
{
	$data = [];
	foreach ($array as $index => $item) {
		$data[$item[$key]] = $item;
	}
	return $data;
}

function isJson($string) {
	
	return is_string($string) && is_array(json_decode($string, true)) && (json_last_error() == JSON_ERROR_NONE);
	
}

/**
 * aes加密
 * @param $data
 * @param $secret_key
 * @param $method
 * @param $iv
 * @param $options
 * @return false|string
 */
function encrypt($data, $secret_key = 'wx', $method = 'AES-128-ECB', $iv = '', $options = 0)
{
    $data = is_array($data) ? json_encode($data) : $data;
    return openssl_encrypt($data, $method, $secret_key, $options, $iv);
}

/**
 * aes解密
 * @param string $data
 * @param $secret_key
 * @param $method
 * @param $iv
 * @param $options
 * @return false|string
 */
function decrypt(string $data, $secret_key = 'wx', $method = 'AES-128-ECB', $iv = '', $options = 0)
{
    return openssl_decrypt($data, $method, $secret_key, $options, $iv);
}


//IP地址拼装和脱敏
function ipAddrAssembly($ipCountry,$ipProvince,$ipCity,$ipArea){
	if (empty($ipCity) && empty($ipArea)) {
		//当不存在地级市信息时，则返回省份信息
		$ipAddress =$ipCountry.($ipProvince ? ' | '.$ipProvince:'');
	} else {
		$ipAddress = $ipCity . ($ipArea ? ' | ' .$ipArea :'');
	}
	$ipAddress=trim($ipAddress,'|');
	return $ipAddress;
}

/**
 * 手机号 银行卡 身份证 脱敏
 */
function hidderData($string,$str,$end){

    return substr_replace($string,'****',$str,$end);
}

function validatePhoneNumber($phoneNumber) {
    $pattern =  '/^1(3[0-9]|4[0145-9]|5[0-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/';
    //$pattern = '^(13\d|14[^23\D]|15\D|16[^013489\D]|17[^9\D]|18\d|19[^4\D])\d{8}$';
    return preg_match($pattern, $phoneNumber);
}

/**
 * 隐藏名字
 * @param $name
 * @return mixed|string
 */
function hideName($name){
    $len = mb_strlen($name, 'utf-8');
    if($len == 2){
        return mb_substr($name, 0, 1, 'utf-8') . '*';
    } else if($len > 2){
        $firstChar = mb_substr($name, 0, 1, 'utf-8');
        $lastChar = mb_substr($name, -1, 1, 'utf-8');
        $middle = str_repeat('*', $len - 2);
        return $firstChar . $middle . $lastChar;
    }
    return $name;
}

/**
 * 系统加密方法
 * @param string $data 要加密的字符串
 * @param string $key  加密密钥
 * @param int $expire  过期时间 单位 秒
 * @return string
 */
function think_encrypt(string $data, string $key = '', int $expire = 0): string
{
    $key  = md5(empty($key) ? env('USER_PWD_OPENSSL_KEY') : $key);
    $data = base64_encode($data);
    $x    = 0;
    $len  = strlen($data);
    $l    = strlen($key);
    $char = '';

    for ($i = 0; $i < $len; $i++) {
        if ($x == $l) $x = 0;
        $char .= substr($key, $x, 1);
        $x++;
    }

    $str = sprintf('%010d', $expire ? $expire + time():0);

    for ($i = 0; $i < $len; $i++) {
        $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1)))%256);
    }
    return str_replace(array('+','/','='),array('-','_',''),base64_encode($str));
}


/**
 * 系统解密方法
 * @param  string $data 要解密的字符串 （必须是think_encrypt方法加密的字符串）
 * @param string $key  加密密钥
 * @return string
 */
function think_decrypt(string $data, string $key = ''): string
{
    $key    = md5(empty($key) ? env('USER_PWD_OPENSSL_KEY') : $key);
    $data   = str_replace(array('-','_'),array('+','/'),$data);
    $mod4   = strlen($data) % 4;
    if ($mod4) {
        $data .= substr('====', $mod4);
    }
    $data   = base64_decode($data);
    $expire = substr($data,0,10);
    $data   = substr($data,10);

    if($expire > 0 && $expire < time()) {
        return '';
    }
    $x      = 0;
    $len    = strlen($data);
    $l      = strlen($key);
    $char   = $str = '';

    for ($i = 0; $i < $len; $i++) {
        if ($x == $l) $x = 0;
        $char .= substr($key, $x, 1);
        $x++;
    }

    for ($i = 0; $i < $len; $i++) {
        if (ord(substr($data, $i, 1))<ord(substr($char, $i, 1))) {
            $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
        }else{
            $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
        }
    }
    return base64_decode($str);
}

//http转https
function httpConvertHttps($url){
    if (!preg_match("/^https:\/\/.+$/",$url)){
        $url=str_replace('http','https',$url);
    }
    return $url;
}

function deleteDirectory($dir) {
    if (!file_exists($dir)) {
        return true;
    }
    if (!is_dir($dir)) {
        return unlink($dir);
    }
    foreach (scandir($dir) as $item) {
        if ($item == '.' || $item == '..') {
            continue;
        }
        if (!deleteDirectory($dir . DIRECTORY_SEPARATOR . $item)) {
            return false;
        }
    }
    return rmdir($dir);
}

//选择数据库
function getSwitchDatabaseModel(string $name,string $host,string $dbname,string $username,string $password,string $port,string $prefix='')
{
    $configs = [
        // 数据库类型
        'type'            => 'mysql',
        // 服务器地址
        'hostname'        => $host,
        // 数据库名
        'database'        => $dbname,
        // 用户名
        'username'        => $username,
        // 密码
        'password'        => $password,
        // 数据库表前缀
        'prefix'          => $prefix,
        // 端口
        'hostport'        => (int)$port,
    ];
    //获取现有的数据库配置信息
    $database_config = \think\facade\Config::get('database');
    //新增数据库参数配置
    $database_config['connections'][$name]= $configs;
    //设置database参数为 修改过的database配置参数
    Config::set($database_config, 'database');
    
    try {
        $connection = Db::connect($name,true);
        // 测试连接是否有效
        $connection->query('SELECT 1');
        return $connection;
    } catch (\Exception $e) {
        // 连接失败时返回false
        return false;
    }
}

function generateRandomString($length): string
{
    // 定义字母表（可以根据需要添加更多字符）
    $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';

    // 生成随机字符串
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }

    return $randomString;
}

//计算分区基数
function calculateRedisRegionDbNum($regionID,$dbNum):int{
    return \app\common\lib\Consts::REGION_REDIS_LIMIT_NUM*$regionID+$dbNum;
}

/**
 * 生成基于取余运算的UUID
 * 支持8位或10位UUID生成
 * 通过 UUID % 总分区数 = 分区ID 来定位分区
 * @param int $totalPartitions 总分区数，默认50
 * @param int $type UUID类型：1=8位UUID，2=10位UUID，默认2
 * @return string UUID字符串
 */
function getUUID($partitionId,$type = 2) {
    $totalPartitions = \app\common\lib\Consts::REGION_ZONE_TOTAL_NUM;
    // 确保分区ID在有效范围内
    $partitionId = max(0, min($totalPartitions - 1, $partitionId));
    
    // 根据type设置UUID范围
    if ($type == 1) {
        // 8位UUID范围：10000000~99999999
        $minUUID = 10000000;
        $maxUUID = 99999999;
    } else {
        // 10位UUID范围：1000000000~9999999999
        $minUUID = 1000000000;
        $maxUUID = 9999999999;
    }
    
    // 计算在该分区ID下可用的UUID范围
    $rangeSize = $maxUUID - $minUUID + 1;
    $partitionSize = intval($rangeSize / $totalPartitions);
    
    // 生成一个随机的基数，确保取余后等于目标分区ID
    $randomMultiplier = mt_rand(0, intval($partitionSize / $totalPartitions));
    $baseUUID = $minUUID + ($randomMultiplier * $totalPartitions) + $partitionId;
    
    // 确保UUID在有效范围内
    if ($baseUUID > $maxUUID) {
        // 如果超出范围，从最小值开始重新计算
        $baseUUID = $minUUID + $partitionId;
    }
    
    // 添加随机偏移，但保持取余结果不变
    $maxOffset = intval(($maxUUID - $baseUUID) / $totalPartitions);
    if ($maxOffset > 0) {
        $randomOffset = mt_rand(0, $maxOffset);
        $baseUUID += $randomOffset * $totalPartitions;
    }
    
    return strval($baseUUID);
}